From 2d04defeac2ebd5e810dd25f2b0e5cb497a0f1b2 Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Tue, 11 Nov 2025 15:31:22 +0000 Subject: [PATCH] timeLimitsManager: Batch-submit usage records to malcontent-timerd This was skipped in the first version of parental controls screen time limits, because we forgot that `RecordUsage()` already allows batch submission of usage records. Rework the code to make one D-Bus call rather than O(N) calls. Signed-off-by: Philip Withnall Part-of: --- js/misc/timeLimitsManager.js | 43 ++++++++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 9 deletions(-) diff --git a/js/misc/timeLimitsManager.js b/js/misc/timeLimitsManager.js index c0dd97ce9..571495142 100644 --- a/js/misc/timeLimitsManager.js +++ b/js/misc/timeLimitsManager.js @@ -227,13 +227,34 @@ export const TimeLimitsManager = GObject.registerClass({ this._updateStateMachine(); } - async _recordUsage(startSecs, endSecs) { - console.debug('Recording usage to the parental controls daemon: ' + - `${this._unixToString(startSecs)} ${this._unixToString(endSecs)}`); + async _recordUsage(records) { + // Build the array of records expected by the D-Bus API + const augmentedRecords = []; + let latestUsageEndSecs = 0; + + for (let i = 0; i < records.length; i++) { + console.debug('Recording usage to the parental controls daemon: ' + + `${this._unixToString(records[i].startSecs)} ${this._unixToString(records[i].endSecs)}`); + + augmentedRecords.push([ + records[i].startSecs, + records[i].endSecs, + 'login-session', + '', + ]); + + // Update the limit of which records to re-send in future. We expect + // all the records to be in order, but it seems more robust to + // assume they might not be, just in case. Records might end up + // being out of order wrt this._latestUsageEndSecs when initially + // loading the session history at startup. + if (records[i].endSecs > latestUsageEndSecs) + latestUsageEndSecs = records[i].endSecs; + } + try { - await this._timerChildProxy.RecordUsageAsync( - [[startSecs, endSecs, 'login-session', '']]); - this._latestUsageEndSecs = endSecs; + await this._timerChildProxy.RecordUsageAsync(augmentedRecords); + this._latestUsageEndSecs = latestUsageEndSecs; } catch (e) { if (e.matches(Gio.DBusError, Gio.DBusError.SERVICE_UNKNOWN)) { // Limits should only be enabled when the daemon is available. @@ -262,7 +283,7 @@ export const TimeLimitsManager = GObject.registerClass({ this._stateTransitions.at(-1).newState === UserState.ACTIVE) { const startSecs = this._stateTransitions.at(-1).wallTimeSecs; const endSecs = this.getCurrentTime(); - await this._recordUsage(startSecs, endSecs); + await this._recordUsage([{startSecs, endSecs}]); } } @@ -715,6 +736,8 @@ export const TimeLimitsManager = GObject.registerClass({ // Record all of the usage records to the parental controls timer daemon // if the parental controls session limits are in place. if (this._parentalControlsManager.sessionLimitsEnabled()) { + const usageRecords = []; + for (var j = 0; j < this._stateTransitions.length - 1; j++) { const start = this._stateTransitions[j]; const end = this._stateTransitions[j + 1]; @@ -731,9 +754,11 @@ export const TimeLimitsManager = GObject.registerClass({ if (endSecs <= this._latestUsageEndSecs) continue; - /* eslint-disable-next-line no-await-in-loop */ - await this._recordUsage(startSecs, endSecs); + usageRecords.push({startSecs, endSecs}); } + + if (usageRecords.length > 0) + await this._recordUsage(usageRecords); } if (this._stateTransitions.length === 0) { -- 2.39.5